{% extends "base.html" %}

{% block title %}系统日志 - XbyJob{% endblock %}

{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
    <h1 class="h2">系统日志</h1>
    <div class="btn-toolbar mb-2 mb-md-0">
        <div class="btn-group me-2">
            <button type="button" class="btn btn-outline-secondary" onclick="refreshLogs()">
                <i class="fas fa-sync-alt me-1"></i>刷新
            </button>
            <button type="button" class="btn btn-outline-info" onclick="exportLogs()">
                <i class="fas fa-download me-1"></i>导出
            </button>
            {% if current_user.is_admin %}
            <button type="button" class="btn btn-outline-danger" onclick="clearLogs()">
                <i class="fas fa-trash me-1"></i>清理日志
            </button>
            {% endif %}
        </div>
    </div>
</div>



<!-- 筛选器 -->
<div class="row mb-3">
    <div class="col-md-2">
        <select class="form-select" id="levelFilter">
            <option value="">全部级别</option>
            <option value="TRACE">跟踪</option>
            <option value="DEBUG">调试</option>
            <option value="INFO">信息</option>
            <option value="NOTICE">注意</option>
            <option value="WARNING">警告</option>
            <option value="ERROR">错误</option>
            <option value="CRITICAL">严重</option>
            <option value="ALERT">告警</option>
            <option value="EMERGENCY">紧急</option>
        </select>
    </div>
    <div class="col-md-2">
        <select class="form-select" id="moduleFilter">
            <option value="">全部模块</option>
            <!-- Web服务模块 -->
            <option value="web.auth">Web认证</option>
            <option value="web.api">Web API</option>
            <option value="web.dashboard">Web仪表板</option>
            <!-- 调度器模块 -->
            <option value="scheduler.scheduler">调度器核心</option>
            <option value="scheduler.tasks">调度任务</option>
            <!-- 执行器模块 -->
            <option value="executor.tasks">执行器任务</option>
            <option value="executor.task_runner">任务运行器</option>
            <option value="executor.dependency_manager">依赖管理器</option>
            <option value="dependency_api">依赖API</option>
            <!-- 共享服务模块 -->
            <option value="shared.notification">通知服务</option>
            <option value="shared.websocket">WebSocket服务</option>
            <option value="shared.startup_task_checker">启动任务检查器</option>
            <option value="shared.service_client">服务客户端</option>
            <!-- Celery服务 -->
            <option value="celery_service">Celery服务</option>
            <!-- 脚本模块 -->
            <option value="scripts.update_all_durations">更新持续时间脚本</option>
            <option value="migrate_last_started_at">迁移脚本</option>
            <!-- 兼容旧模块名 -->
            <option value="auth">用户认证(旧)</option>
            <option value="task_api">任务API(旧)</option>
            <option value="script_api">脚本API(旧)</option>
            <option value="admin_api">管理API(旧)</option>
            <option value="scheduler">调度器(旧)</option>
            <option value="executor">执行器(旧)</option>
            <option value="system">系统</option>
            <option value="web">网站(旧)</option>
            <option value="database">数据库</option>
            <option value="http_middleware">HTTP中间件</option>
            <option value="business">业务</option>
            <option value="data">数据</option>
            <option value="integration">集成</option>
            <option value="workflow">工作流</option>
            <option value="cache">缓存</option>
            <option value="notification">通知(旧)</option>
        </select>
    </div>
    <div class="col-md-2">
        <select class="form-select" id="actionFilter">
            <option value="">全部操作</option>
            <option value="login">登录</option>
            <option value="logout">登出</option>
            <option value="create">创建</option>
            <option value="update">更新</option>
            <option value="delete">删除</option>
            <option value="execute">执行</option>
            <option value="request_start">请求开始</option>
            <option value="request_complete">请求完成</option>
            <option value="request_exception">请求异常</option>
        </select>
    </div>
    <div class="col-md-2">
        <select class="form-select" id="resourceTypeFilter">
            <option value="">全部资源</option>
            <option value="user">用户</option>
            <option value="task">任务</option>
            <option value="script">脚本</option>
            <option value="file">文件</option>
            <option value="http">HTTP</option>
            <option value="database">数据库</option>
            <option value="system">系统</option>
            <option value="cache">缓存</option>
            <option value="notification">通知</option>
        </select>
    </div>
    <div class="col-md-2">
        <select class="form-select" id="severityFilter">
            <option value="">全部严重程度</option>
            <option value="0">0 - 正常</option>
            <option value="1">1 - 轻微</option>
            <option value="2">2 - 一般</option>
            <option value="3">3 - 重要</option>
            <option value="4">4 - 严重</option>
            <option value="5">5 - 紧急</option>
        </select>
    </div>
</div>

<div class="row mb-3">
    <div class="col-md-2">
        <input type="date" class="form-control" id="dateFilter">
    </div>
    <div class="col-md-2">
        <input type="text" class="form-control" id="tagsFilter" placeholder="标签筛选...">
    </div>
    <div class="col-md-4">
        <input type="text" class="form-control" id="searchInput" placeholder="搜索日志内容...">
    </div>
    <div class="col-md-2">
        <button type="button" class="btn btn-outline-primary w-100" onclick="applyFilters()">
            <i class="fas fa-filter me-1"></i>筛选
        </button>
    </div>
    <div class="col-md-2">
        <button type="button" class="btn btn-outline-secondary w-100" onclick="clearFilters()">
            <i class="fas fa-times me-1"></i>清除
        </button>
    </div>
</div>

<!-- 日志统计卡片 -->
<div class="row mb-4">
    <div class="col-md-4">
        <div class="card text-center">
            <div class="card-body">
                <h5 class="card-title text-primary" id="totalLogs">{{ stats.total_logs if stats else '-' }}</h5>
                <p class="card-text">总日志数</p>
            </div>
        </div>
    </div>
    <div class="col-md-4">
        <div class="card text-center">
            <div class="card-body">
                <h5 class="card-title text-danger" id="errorLogs">{{ stats.error_logs if stats else '-' }}</h5>
                <p class="card-text">错误日志</p>
            </div>
        </div>
    </div>
    <div class="col-md-4">
        <div class="card text-center">
            <div class="card-body">
                <h5 class="card-title text-warning" id="warningLogs">{{ stats.warning_logs if stats else '-' }}</h5>
                <p class="card-text">警告日志</p>
            </div>
        </div>
    </div>
</div>



<!-- 日志列表 -->
<div class="card">
    <div class="card-body">
        <div class="table-responsive">
            <table class="table table-striped table-sm" id="logsTable">
                <thead>
                    <tr>
                        <th width="130">时间</th>
                        <th width="70">级别</th>
                        <th width="80">操作</th>
                        <th width="80">模块</th>
                        <th width="80">资源</th>
                        <th width="80">用户</th>
                        <th width="80">执行时间</th>
                        <th>消息</th>
                        <th width="80">操作</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td colspan="7" class="text-center">
                            <div class="spinner-border text-primary" role="status">
                                <span class="visually-hidden">加载中...</span>
                            </div>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
        
        <!-- 分页 -->
        <nav aria-label="日志分页">
            <ul class="pagination justify-content-center" id="pagination">
            </ul>
        </nav>
    </div>
</div>

<!-- 日志详情模态框 -->
<div class="modal fade" id="logDetailModal" tabindex="-1">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">日志详情</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <div class="row mb-3">
                    <div class="col-md-6">
                        <p><strong>时间:</strong> <span id="detailTimestamp">-</span></p>
                        <p><strong>级别:</strong> <span id="detailLevel">-</span></p>
                        <p><strong>操作:</strong> <span id="detailAction">-</span></p>
                        <p><strong>模块:</strong> <span id="detailModule">-</span></p>
                        <p><strong>资源类型:</strong> <span id="detailResourceType">-</span></p>
                        <p><strong>资源ID:</strong> <span id="detailResourceId">-</span></p>
                        <p><strong>严重程度:</strong> <span id="detailSeverity">-</span></p>
                    </div>
                    <div class="col-md-6">
                        <p><strong>用户:</strong> <span id="detailUser">-</span></p>
                        <p><strong>IP地址:</strong> <span id="detailIp">-</span></p>
                        <p><strong>用户代理:</strong> <span id="detailUserAgent">-</span></p>
                        <p><strong>执行时间:</strong> <span id="detailExecutionTime">-</span></p>
                        <p><strong>状态码:</strong> <span id="detailStatusCode">-</span></p>
                        <p><strong>请求ID:</strong> <span id="detailRequestId">-</span></p>
                        <p><strong>标签:</strong> <span id="detailTags">-</span></p>
                    </div>
                </div>
                
                <div class="row">
                    <div class="col-12">
                        <p><strong>消息:</strong></p>
                        <div class="bg-light p-3 rounded">
                            <pre id="detailMessage" class="mb-0">-</pre>
                        </div>
                    </div>
                </div>
                
                <div class="row mt-3" id="detailDataSection" style="display: none;">
                    <div class="col-12">
                        <p><strong>附加数据:</strong></p>
                        <div class="bg-light p-3 rounded">
                            <pre id="detailData" class="mb-0">-</pre>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<!-- 清理日志确认模态框 -->
{% if current_user.is_admin %}
<div class="modal fade" id="clearLogsModal" tabindex="-1">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">清理系统日志</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <p>请选择要清理的日志：</p>
                <div class="form-check">
                    <input class="form-check-input" type="radio" name="clearType" id="clear7days" value="7" checked>
                    <label class="form-check-label" for="clear7days">
                        清理7天前的日志
                    </label>
                </div>
                <div class="form-check">
                    <input class="form-check-input" type="radio" name="clearType" id="clear30days" value="30">
                    <label class="form-check-label" for="clear30days">
                        清理30天前的日志
                    </label>
                </div>
                <div class="form-check">
                    <input class="form-check-input" type="radio" name="clearType" id="clearAll" value="all">
                    <label class="form-check-label" for="clearAll">
                        清理所有日志
                    </label>
                </div>
                <div class="alert alert-warning mt-3">
                    <i class="fas fa-exclamation-triangle me-2"></i>
                    此操作不可恢复，请谨慎操作！
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                <button type="button" class="btn btn-danger" onclick="confirmClearLogs()">确认清理</button>
            </div>
        </div>
    </div>
</div>
{% endif %}

{% endblock %}

{% block scripts %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
let currentPage = 1;
let currentFilters = {};


$(document).ready(function() {
    // 加载数据
    loadLogs();
    loadLogStats();
    
    // 设置默认日期为今天
    $('#dateFilter').val(new Date().toISOString().split('T')[0]);
});

function loadLogStats() {
    // 统计卡片数据已在服务器端渲染，无需额外处理
    console.log('日志统计数据已在服务器端渲染');
}





function loadLogs(page = 1) {
    currentPage = page;
    
    const params = new URLSearchParams({
        page: page,
        per_page: 50,
        ...currentFilters
    });
    
    $('#logsTable tbody').html(`
        <tr>
            <td colspan="7" class="text-center">
                <div class="spinner-border text-primary" role="status">
                    <span class="visually-hidden">加载中...</span>
                </div>
            </td>
        </tr>
    `);
    
    $.get('/dashboard/api/logs?' + params.toString())
        .done(function(response) {
            if (response.success) {
                renderLogs(response.data.logs);
                renderPagination(response.data.pagination);
            } else {
                showAlert('获取日志失败: ' + response.message, 'danger');
            }
        })
        .fail(function() {
            showAlert('网络错误，请稍后重试', 'danger');
        });
}

function renderLogs(logs) {
    const tbody = $('#logsTable tbody');
    tbody.empty();
    
    if (logs.length === 0) {
        tbody.append(`
            <tr>
                <td colspan="7" class="text-center text-muted">暂无日志记录</td>
            </tr>
        `);
        return;
    }
    
    logs.forEach(function(log) {
        const levelBadge = getLevelBadge(log.level);
        const timestamp = new Date(log.timestamp).toLocaleString();
        const message = log.message.length > 80 ? 
            log.message.substring(0, 80) + '...' : 
            log.message;
        const executionTime = log.execution_time ? `${log.execution_time}ms` : '-';
        
        tbody.append(`
            <tr>
                <td><small>${timestamp}</small></td>
                <td>${levelBadge}</td>
                <td>${log.action || '-'}</td>
                <td><span class="badge bg-secondary">${log.module}</span></td>
                <td>${log.resource_type || '-'}</td>
                <td>${log.username || '-'}</td>
                <td>${executionTime}</td>
                <td class="text-truncate" style="max-width: 250px;" title="${log.message}">${message}</td>
                <td>
                    <button class="btn btn-sm btn-outline-primary" onclick="viewLogDetail(${log.id})" title="详情">
                        <i class="fas fa-eye"></i>
                    </button>
                </td>
            </tr>
         `);
     });
 }

function renderPagination(pagination) {
    const nav = $('#pagination');
    nav.empty();
    
    if (pagination.pages <= 1) return;
    
    // 上一页
    nav.append(`
        <li class="page-item ${!pagination.has_prev ? 'disabled' : ''}">
            <a class="page-link" href="#" onclick="loadLogs(${pagination.page - 1})">上一页</a>
        </li>
    `);
    
    // 页码
    const startPage = Math.max(1, pagination.page - 2);
    const endPage = Math.min(pagination.pages, pagination.page + 2);
    
    for (let i = startPage; i <= endPage; i++) {
        nav.append(`
            <li class="page-item ${i === pagination.page ? 'active' : ''}">
                <a class="page-link" href="#" onclick="loadLogs(${i})">${i}</a>
            </li>
        `);
    }
    
    // 下一页
    nav.append(`
        <li class="page-item ${!pagination.has_next ? 'disabled' : ''}">
            <a class="page-link" href="#" onclick="loadLogs(${pagination.page + 1})">下一页</a>
        </li>
    `);
}

function applyFilters() {
    currentFilters = {};
    
    const level = $('#levelFilter').val();
    if (level) currentFilters.level = level;
    
    const module = $('#moduleFilter').val();
    if (module) currentFilters.module = module;
    
    const action = $('#actionFilter').val();
    if (action) currentFilters.action = action;
    
    const resourceType = $('#resourceTypeFilter').val();
    if (resourceType) currentFilters.resource_type = resourceType;
    
    const severity = $('#severityFilter').val();
    if (severity) currentFilters.severity = severity;
    
    const date = $('#dateFilter').val();
    if (date) currentFilters.date = date;
    
    const tags = $('#tagsFilter').val().trim();
    if (tags) currentFilters.tags = tags;
    
    const search = $('#searchInput').val().trim();
    if (search) currentFilters.search = search;
    
    loadLogs(1);
}

function clearFilters() {
    $('#levelFilter').val('');
    $('#moduleFilter').val('');
    $('#actionFilter').val('');
    $('#resourceTypeFilter').val('');
    $('#severityFilter').val('');
    $('#dateFilter').val('');
    $('#tagsFilter').val('');
    $('#searchInput').val('');
    currentFilters = {};
    loadLogs(1);
}

function refreshLogs() {
    loadLogs(currentPage);
    loadLogStats();
}

function viewLogDetail(logId) {
    $.get(`/dashboard/api/logs/${logId}`)
        .done(function(response) {
            if (response.success) {
                const log = response.data;
                $('#detailTimestamp').text(new Date(log.timestamp).toLocaleString());
                $('#detailLevel').html(getLevelBadge(log.level));
                $('#detailAction').text(log.action || '-');
                $('#detailModule').text(log.module);
                $('#detailResourceType').text(log.resource_type || '-');
                $('#detailResourceId').text(log.resource_id || '-');
                $('#detailSeverity').text(log.severity || '-');
                $('#detailUser').text(log.username || '系统');
                $('#detailIp').text(log.ip_address || '-');
                $('#detailUserAgent').text(log.user_agent || '-');
                $('#detailExecutionTime').text(log.execution_time ? `${log.execution_time}ms` : '-');
                $('#detailStatusCode').text(log.status_code || '-');
                $('#detailRequestId').text(log.request_id || '-');
                $('#detailTags').text(log.tags || '-');
                $('#detailMessage').text(log.message);
                
                // 显示附加数据（如果有）
                const hasDetails = log.details || log.metadata;
                if (hasDetails) {
                    try {
                        let displayData = {};
                        if (log.details) {
                            const details = typeof log.details === 'string' ? JSON.parse(log.details) : log.details;
                            displayData.details = details;
                        }
                        if (log.metadata) {
                            const metadata = typeof log.metadata === 'string' ? JSON.parse(log.metadata) : log.metadata;
                            displayData.metadata = metadata;
                        }
                        $('#detailData').text(JSON.stringify(displayData, null, 2));
                        $('#detailDataSection').show();
                    } catch (e) {
                        $('#detailData').text(log.details || log.metadata);
                        $('#detailDataSection').show();
                    }
                } else {
                    $('#detailDataSection').hide();
                }
                
                $('#logDetailModal').modal('show');
            } else {
                showAlert('获取日志详情失败: ' + response.message, 'danger');
            }
        })
        .fail(function() {
            showAlert('网络错误，请稍后重试', 'danger');
        });
}

function clearLogs() {
    $('#clearLogsModal').modal('show');
}

function confirmClearLogs() {
    const clearType = $('input[name="clearType"]:checked').val();
    
    $.ajax({
        url: '/dashboard/api/logs/clear',
        method: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({type: clearType})
    })
    .done(function(response) {
        if (response.success) {
            $('#clearLogsModal').modal('hide');
            showAlert('日志清理成功', 'success');
            loadLogs(1);
            loadLogStats();
        } else {
            showAlert('清理失败: ' + response.message, 'danger');
        }
    })
    .fail(function() {
        showAlert('网络错误，请稍后重试', 'danger');
    });
}

function exportLogs() {
    // 获取当前筛选条件
    const params = new URLSearchParams({
        ...currentFilters,
        export: 'csv'
    });
    
    // 创建下载链接
    const url = '/dashboard/api/logs/export?' + params.toString();
    
    // 创建隐藏的a标签进行下载
    const link = document.createElement('a');
    link.href = url;
    link.download = `system_logs_${new Date().toISOString().split('T')[0]}.csv`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    
    showAlert('日志导出已开始', 'info');
}

function getLevelBadge(level) {
    const badges = {
        'DEBUG': '<span class="badge bg-secondary">调试</span>',
        'INFO': '<span class="badge bg-info">信息</span>',
        'WARNING': '<span class="badge bg-warning text-dark">警告</span>',
        'ERROR': '<span class="badge bg-danger">错误</span>'
    };
    return badges[level] || `<span class="badge bg-secondary">${level}</span>`;
}

function getTypeBadge(logType) {
    const badges = {
        'USER_ACTION': '<span class="badge bg-primary">用户操作</span>',
        'TASK_OPERATION': '<span class="badge bg-success">任务操作</span>',
        'FILE_OPERATION': '<span class="badge bg-info">文件操作</span>',
        'SYSTEM_EVENT': '<span class="badge bg-warning text-dark">系统事件</span>',
        'SECURITY_EVENT': '<span class="badge bg-danger">安全事件</span>',
        'LOGIN_ATTEMPT': '<span class="badge bg-dark">登录尝试</span>',
        'API_CALL': '<span class="badge bg-secondary">API调用</span>',
        'CLEANUP_TASK': '<span class="badge bg-purple text-white">清理任务</span>'
    };
    return badges[logType] || `<span class="badge bg-light text-dark">${logType || '未知'}</span>`;
}

function getResourceInfo(log) {
    if (log.resource_type && log.resource_id) {
        return `${log.resource_type}:${log.resource_id}`;
    }
    return null;
}

function showAlert(message, type) {
    // 使用基础模板中定义的全局showMessage函数（即showToast）
    if (typeof window.showMessage === 'function') {
        // 映射类型到Toast支持的类型
        let toastType = type;
        switch(type) {
            case 'danger':
                toastType = 'error';
                break;
            case 'warning':
                toastType = 'warning';
                break;
            case 'success':
                toastType = 'success';
                break;
            default:
                toastType = 'info';
        }
        showMessage(message, toastType, 3000);
    } else {
        // 如果全局函数不可用，回退到原来的实现
        const alertHtml = `
            <div class="alert alert-${type} alert-dismissible fade show" role="alert">
                ${message}
                <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
            </div>
        `;
        
        $('.container-fluid').prepend(alertHtml);
        
        setTimeout(function() {
            $('.alert').alert('close');
        }, 3000);
    }
}
</script>
{% endblock %}